#pragma semicolon 1
 
#include <sourcemod>

// #define DEBUG 1

#define VERSION "1.1"
#define NAME "SourceBB Verification"

// How often (in seconds) clients are allowed to use !verify
#define MAXRATE 300.0

// Message color to use for client messages
#define MSGCOLOR 4

new Handle:g_hVerifyDatabase;
new Handle:g_hRateLimit[MAXPLAYERS+1];
new Handle:g_hCvarDBConfName;
new bool:g_bCanVerify[MAXPLAYERS+1];

public Plugin:myinfo = {
	name = NAME,
	author = "psychonic",
	description = "SourceBB In-Game Verification",
	version = VERSION,
	url = "http://www.sourcebb.org/"
};

public OnPluginStart()
{
	RegConsoleCmd("say", ChatParse);
	RegConsoleCmd("say2",  ChatParse);
	RegConsoleCmd("say_team",  ChatParse);
	
	CreateConVar("sm_verify_version", VERSION, NAME, FCVAR_PLUGIN|FCVAR_NOTIFY);
	g_hCvarDBConfName = CreateConVar("sm_verify_dbconfname", "verification", "Database config name for verification db", FCVAR_PLUGIN);
}

public OnConfigsExecuted()
{
	if (g_hVerifyDatabase == INVALID_HANDLE)
	{
		decl String:szDBConfName[64];
		GetConVarString(g_hCvarDBConfName, szDBConfName, sizeof(szDBConfName));
		SQL_TConnect(OnConnectedToDatabase, szDBConfName);
	}
}

public OnConnectedToDatabase(Handle:owner, Handle:hndl, const String:error[], any:data)
{	
	if (hndl == INVALID_HANDLE)
	{
		SetFailState("Cannot connect to database");
	}
	
	g_hVerifyDatabase = hndl;
}

public OnClientPostAdminCheck(client)
{
	g_hRateLimit[client] = INVALID_HANDLE;
	g_bCanVerify[client] = true;
}

public Action:ChatParse(client, args)
{
	if (g_hVerifyDatabase == INVALID_HANDLE
		|| !IsClientInGame(client)
		|| !IsClientConnected(client)
		|| IsFakeClient(client)
		)
	{
		return Plugin_Continue;
	}
	
	decl String:szChatMessage[8];
	GetCmdArg(1, szChatMessage, sizeof(szChatMessage));
	if (strncmp(szChatMessage, "!verify", 7, false) == 0)
	{
		if (g_bCanVerify[client])
		{
			g_bCanVerify[client] = false;
			
			decl String:szTempSteamId[25];
			decl String:szSteamId[49];
			GetClientAuthString(client, szTempSteamId, sizeof(szTempSteamId));
			SQL_EscapeString(g_hVerifyDatabase, szTempSteamId, szSteamId, sizeof(szSteamId));
			decl String:szQuery[1024];
			Format(szQuery, sizeof(szQuery), "SELECT identity FROM sm_admins WHERE identity='%s'", szSteamId);
#if defined DEBUG
			PrintToChat(client, "DEBUG: \"%s\"", szQuery);
#endif
			SQL_TQuery(g_hVerifyDatabase, OnCheckExists, szQuery, GetClientUserId(client));
		}
		else
		{
			decl String:szSteamId[25];
			GetClientAuthString(client, szSteamId, sizeof(szSteamId));
			
			PrintToChat(client, "%cTrying to verify again too soon. Please try again after 5 minutes.", MSGCOLOR);
			LogMessage("%N (%s) trying to verify too often", client, szSteamId);
		}
	
		return Plugin_Stop;
	}
	
	return Plugin_Continue;
}

public OnCheckExists(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	new client = GetClientOfUserId(userid);
	
	// Make sure the client didn't disconnect before callback executed
	if (client == 0 || !IsClientInGame(client))
	{
		return;
	}
	
	if (hndl == INVALID_HANDLE)
	{
		PrintToChat(client, "%cThere was a problem verifying your account", MSGCOLOR);
		LogError("Bad query handle on existance check (sm_admins)");
		return;
	}
	
	if (SQL_GetRowCount(hndl) < 1)
	{
		// not in sm_admins, check sm_admins_pre
		decl String:szTempSteamId[25];
		decl String:szSteamId[49];
		GetClientAuthString(client, szTempSteamId, sizeof(szTempSteamId));
		SQL_EscapeString(g_hVerifyDatabase, szTempSteamId, szSteamId, sizeof(szSteamId));
		decl String:szQuery[1024];
		Format(szQuery, sizeof(szQuery), "SELECT name,id FROM sm_admins_pre WHERE identity='%s'", szSteamId);
#if defined DEBUG
		PrintToChat(client, "DEBUG: \"%s\"", szQuery);
#endif
		SQL_TQuery(g_hVerifyDatabase, OnCheckPreExists, szQuery, userid);
	}
	else
	{
		PrintToChat(client, "%cYou are already verified", MSGCOLOR);
		StartCooldown(client);
	}
}

public OnCheckPreExists(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	new client = GetClientOfUserId(userid);
	
	// Make sure the client didn't disconnect before callback executed
	if (client == 0 || !IsClientInGame(client))
	{
		return;
	}
	
	if (hndl == INVALID_HANDLE)
	{
		PrintToChat(client, "%cThere was a problem verifying your account", MSGCOLOR);
		LogError("Bad query handle on existance check (sm_admins_pre)");
		return;
	}
	
	if (SQL_GetRowCount(hndl) > 0)
	{
		SQL_FetchRow(hndl);
		decl String:szTempName[49];
		decl String:szTempID[49];
		SQL_FetchString(hndl, 0, szTempName, sizeof(szTempName));
		SQL_FetchString(hndl, 1, szTempID, sizeof(szTempID));
		
		decl String:szTempSteamId[25];
		GetClientAuthString(client, szTempSteamId, sizeof(szTempSteamId));
			
			
		decl String:szName[99];
		decl String:szSteamId[49];
		decl String:szSBBId[49];
			
		SQL_EscapeString(g_hVerifyDatabase, szTempName, szName, sizeof(szName));
		SQL_EscapeString(g_hVerifyDatabase, szTempID, szSBBId, sizeof(szSBBId));
		SQL_EscapeString(g_hVerifyDatabase, szTempSteamId, szSteamId, sizeof(szSteamId));
			
		decl String:szQuery[1024];
		Format(szQuery, sizeof(szQuery),
			"INSERT INTO sm_admins (id,name,authtype,identity,immunity,flags) VALUES ('%s','%s','steam','%s',0,'')",
			szSBBId, szName, szSteamId);
#if defined DEBUG
		PrintToChat(client, "DEBUG: \"%s\"", szQuery);
#endif
		SQL_TQuery(g_hVerifyDatabase, OnVerifyInsert, szQuery, userid);
	}
	else
	{
		PrintToChat(client, "%cPlease add your SteamID on our forums.", MSGCOLOR);
		StartCooldown(client);
	}
}

public OnVerifyInsert(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	new client = GetClientOfUserId(userid);
	
	// Make sure the client didn't disconnect before callback executed
	if (client == 0 || !IsClientInGame(client))
	{
		return;
	}
	
	decl String:szSteamId[25];
	GetClientAuthString(client, szSteamId, sizeof(szSteamId));
	
	PrintToChat(client, "%cVerification Successful!", MSGCOLOR);
	LogMessage("%N (%s) verified successfully", client, szSteamId);
	
	StartCooldown(client);
}

StartCooldown(client)
{
	g_hRateLimit[client] = CreateTimer(MAXRATE, RateTimer, client, TIMER_FLAG_NO_MAPCHANGE);
}

public Action:RateTimer(Handle:timer, any:client)
{
	g_bCanVerify[client] = true;
	g_hRateLimit[client] = INVALID_HANDLE;
	
	return Plugin_Stop; 
}